package com.mushiengine.core {
import asmock.framework.Expect;

import asmock.framework.constraints.Is;

import com.mushiengine.collection.HashMap;
import com.mushiengine.collection.IMap;
import com.mushiengine.test.MockTestCase;
import com.mushiengine.test.objects.ExampleBean;
import com.mushiengine.test.objects.InjectedBean;

public class BeanLoaderTest extends MockTestCase{

    private var _mockBeanDefLoader:IBeanDefinitionLoader;
    private var _mockHashMap:IMap;
    private var _mockInjector:IInjector;
    private var _beanLoader:BeanLoader;

    public function BeanLoaderTest() {
        super([IMap,IBeanDefinitionLoader, IInjector]);
    }


    public override function setUp():void {
        super.setUp();
        _mockBeanDefLoader = IBeanDefinitionLoader(mockRepository.createStrict(IBeanDefinitionLoader));
        _mockHashMap = IMap(mockRepository.createStrict(IMap));
        _mockInjector = IInjector(mockRepository.createStrict(IInjector));

        _beanLoader = new BeanLoader(_mockHashMap, _mockInjector);


    }

    public function testThatgetDescriptionsIsCalled():void {
        var testDefinitionMap:IMap = genDescMap();
        Expect.call(_mockBeanDefLoader.getDescriptions()).returnValue(genDescMap());
        Expect.call(_mockInjector.injectViaClass(ExampleBean)).returnValue(new ExampleBean()).constraints([
            Is.notNull()
        ]).repeat.twice();
        Expect.call(_mockHashMap.put("", "")).constraints([
            Is.notNull(),
            Is.notNull()
        ]).repeat.twice();
        mockRepository.replayAll();
        _beanLoader.loadBeanDefinition(_mockBeanDefLoader);
        mockRepository.verifyAll();
    }

    public function xtestThatCorrectInstanceIsCreated():void {
        Expect.call(_mockBeanDefLoader.getDescriptions()).returnValue(genDescMap());
        Expect.call(_mockInjector.injectViaClass(InjectedBean)).constraints([
            Is.notNull()
        ]).returnValue(new InjectedBean());
        Expect.call(_mockInjector.injectViaClass(ExampleBean)).constraints([
            Is.notNull()
        ]).returnValue(new ExampleBean());

        mockRepository.replayAll();
        _beanLoader.loadBeanDefinition(_mockBeanDefLoader);
        assertTrue(Diggbe.getBean("expBean") is ExampleBean);
        assertTrue(Diggbe.getBean("injectedBean") is InjectedBean);

        mockRepository.verifyAll();
    }

    private function genDescMap():IMap {
        var map:IMap = new HashMap();

        map.put("expBean", "com.mushiengine.test.objects::ExampleBean");
        map.put("injectedBean", "com.mushiengine.test.objects::InjectedBean");

        return map;
    }

    public function testInjectorIsCalledWhenInstanceIsCreated():void {
        var injBean:InjectedBean = new InjectedBean();

        Expect.call(_mockInjector.injectViaClass(InjectedBean)).ignoreArguments().returnValue(injBean).repeat.twice();
        Expect.call(_mockHashMap.put("", "")).ignoreArguments().repeat.twice();
        mockRepository.replayAll();
        _beanLoader.createdBeanInstances(genDescMap());
        mockRepository.verifyAll();
    }

    public function testInjectorIsCalledWhenAnInstanceIsPassedIn():void {
        var injBean:InjectedBean = new InjectedBean();
        Expect.call(_mockInjector.injectViaInstance(injBean)).returnValue(injBean).constraints(
                [
                    Is.notNull()
                ]
                ).returnValue(injBean);
        Expect.call(_mockHashMap.put("inject3", injBean));
        mockRepository.replayAll();
        _beanLoader.addbean("inject3", injBean);
        mockRepository.verifyAll();
    }

    public function testAbleToGetBean():void {
        var exampleBean:ExampleBean = new ExampleBean();
        Expect.call(_mockInjector.injectViaInstance(exampleBean)).ignoreArguments().returnValue(exampleBean);
        Expect.call(_mockHashMap.put("", "")).ignoreArguments();
        Expect.call(_mockHashMap.getValue("expBean3")).ignoreArguments().returnValue(new ExampleBean());
        mockRepository.replayAll();
        _beanLoader.addbean("expBean3", exampleBean);
        assertTrue(_beanLoader.getBean("expBean3") is ExampleBean);
        mockRepository.verifyAll();
    }

    public function testThatBeanCanBeRemoved():void {
        _beanLoader.addbean("expBean4", new ExampleBean());
        _beanLoader.removeBean("expBean4");

        assertNull(_beanLoader.getBean("expBean4"));
    }
}
}